A data buffer is a software procedure or a hardware device used to compensate for a difference in rate of flow of data or a difference in time of occurrence of data transfer events. For example, a computer may need to write data to a disk drive. The computer transfer rate may be higher than that of the disk drive, or the disk drive may need to wait until electromechanical events have occurred such as positioning a head over the proper track and sector. Similarly, a data buffer may be used for data transfer between independent processes within a computer or between computers. A data buffer may be a separate physical hardware device or a data buffer may simply be an area of storage that is temporarily reserved for use in performing data transfer.
In general, in an operating system, many processes share main memory. It is expensive to dedicate large blocks of main memory to each process. Instead, in many computer systems, virtual addressing is used in which virtual addresses are translated by a combination of hardware and software into addresses that at any given time might map to peripheral devices such as disks or to addresses that access main memory. One strategy for remapping virtual addresses from the main memory to a disk or other peripheral devices is on a "least recently used" basis. That is, if a process has recently used a block of virtual addresses assigned to main memory, the virtual addresses will remain mapped to main memory. If the addresses are not used, the content of the main memory area may be written to disk, freeing the main memory for use by other processes, possibly at a different virtual address. A processor may then reference a virtual address corresponding to a page that is on a disk (page fault), requiring a page to be moved from the disk into main memory. In general, page faults have a substantial negative impact on performance.
A common data structure for a buffer is a ring, implemented in an area of memory that is shared by both a writing device or process and a reading device or process. In a typical implementation, there is a beginning address, an end address, a write pointer and a read pointer. Initially, the write pointer and the read pointer are at the beginning address. A writing device writes into the ring buffer, moving the write pointer to the end of the newly written data. A reading device reads data at the read pointer, moving the read pointer as data is read. When the write pointer reaches the end address of the ring, the write pointer is moved ("wrapped around") to the beginning address. Various safeguards are implemented to ensure that the write pointer can never overlap the read pointer.
There are two aspects of the typical ring buffer just described that can negatively affect performance. The first performance loss results from the fact that data can be wrapped around from the end address to the beginning address, but may need to be sent or read as a contiguous block. The writer may be required to write two separate blocks. Similarly, the reading device may be forced to perform two separate read operations, one from the beginning address of the data block to the end address of the buffer and another from the beginning address of the buffer to the end address of the data block. In addition, the reading device must then reconstruct a contiguous block of data, perhaps requiring copy operations to place the two sets of data into contiguous memory or allocation of temporary memory. The second performance loss results from virtual memory page faults. If a ring buffer is implemented in virtual memory, the buffer is repeatedly using new areas of the buffer that may not have been used recently. Therefore, there is a high probability of encountering page faults. There is a need for a buffer having improved performance by reducing wrap arounds and page faults.